import { WebSocketServer } from 'ws';
import http from 'http';
import fs from 'fs';
import path from 'path';
import { fork } from 'child_process';
import { fileURLToPath } from 'url';
import { SAMPLE_RATE, CHANNELS, BIT_DEPTH, FRAME_SIZE, SEGMENT_FRAMES, OUTPUT_DIR } from './config.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 确保输出目录存在
const absoluteOutputDir = path.resolve(OUTPUT_DIR);
if (!fs.existsSync(absoluteOutputDir)) {
    fs.mkdirSync(absoluteOutputDir, { recursive: true });
    console.log('创建输出目录:', absoluteOutputDir);
}

// 子进程：专门写 OPUS，避免主进程阻塞
const workerPath = path.join(__dirname, 'opus_worker.js');
const worker = fork(workerPath, [], { stdio: ['ignore', 'inherit', 'inherit', 'ipc'] });
let workerReady = false;
let workerExited = false;
let isShuttingDown = false;

worker.on('message', (msg) => {
    if (!msg || typeof msg !== 'object') return;
    if (msg.type === 'ready') workerReady = true;
    if (msg.type === 'error') console.error('写入子进程错误:', msg.message);
    if (msg.type === 'exited') workerExited = true;
});

worker.on('exit', (code, signal) => {
    workerExited = true;
    if (code !== 0) console.error('写入子进程异常退出:', code, signal || '');
});

worker.on('error', (err) => {
    workerExited = true;
    console.error('写入子进程进程错误:', err?.message || err);
});

worker.send({
    type: 'init',
    config: {
        sampleRate: SAMPLE_RATE,
        channels: CHANNELS,
        bitDepth: BIT_DEPTH,
        outputDir: absoluteOutputDir,
    },
});

class OpusWebSocketServer {
    constructor(options = {}) {
        this.port = options.port || 4000;
        this.wss = null;
        this.httpServer = null;
        this.connections = new Map(); // 存储连接信息
        this.fileSeq = 0;
        
        this.initWebSocketServer();
    }

    initWebSocketServer() {
        this.httpServer = http.createServer((request, response) => {
            response.writeHead(200);
            response.end('Opus WebSocket Server');
        });

        this.wss = new WebSocketServer({ server: this.httpServer });

        this.wss.on('connection', (socket, request) => {
            const origin = request?.headers?.origin || '';
            const deviceId = request?.headers?.['device-id'] || 'unknown';
            const clientId = request?.headers?.['client-id'] || 'unknown';
            
            console.log('OPUS客户端已连接:', `${deviceId}:${clientId} from ${origin}`);
            
            // 初始化连接状态
            const connectionInfo = {
                deviceId,
                clientId,
                frames: [],
                frameCount: 0,
                totalBytes: 0,
                messageCount: 0
            };
            
            this.connections.set(socket, connectionInfo);

            socket.on('message', (data, isBinary) => {
                try {
                    this.handleOpusData(socket, data, isBinary);
                } catch (error) {
                    console.error('处理OPUS数据时出错:', error.message);
                }
            });

            socket.on('close', (code, reason) => {
                const reasonText = Buffer.isBuffer(reason) ? reason.toString() : String(reason || '');
                console.log('OPUS客户端已断开连接, 代码:', code, '原因:', reasonText);
                
                // 保存剩余数据
                this.flushConnection(socket, true);
                this.connections.delete(socket);
            });

            socket.on('error', (error) => {
                console.error('WebSocket连接错误:', error.message);
                this.connections.delete(socket);
            });
        });

        this.httpServer.listen(this.port, () => {
            console.log(`OPUS WebSocket服务器已启动，监听端口 ${this.port}`);
            console.log('分片帧数=', SEGMENT_FRAMES);
        });
    }

    handleOpusData(socket, data, isBinary) {
        const connectionInfo = this.connections.get(socket);
        if (!connectionInfo) return;

        try {
            if (isBinary) {
                const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
                connectionInfo.totalBytes += buf.length;
                connectionInfo.messageCount++;
                
                console.log(`收到OPUS帧 ${connectionInfo.messageCount}: ${buf.length} 字节`);
                
                // 将OPUS帧添加到缓冲区
                connectionInfo.frames.push(buf);
                connectionInfo.frameCount++;
                
                // 按帧数分片：每SEGMENT_FRAMES帧保存一个文件
                if (connectionInfo.frameCount >= SEGMENT_FRAMES) {
                    this.flushConnection(socket, false);
                }
            } else {
                const text = Buffer.isBuffer(data) ? data.toString() : String(data);
                console.log('收到文本消息:', text);
            }
        } catch (error) {
            console.error('处理OPUS数据失败:', error);
        }
    }

    flushConnection(socket, final = false) {
        const connectionInfo = this.connections.get(socket);
        if (!connectionInfo || connectionInfo.frames.length === 0) return;

        const safe = (s) => String(s ?? 'unknown').replace(/[^a-zA-Z0-9_-]/g, '-');
        const name = `${safe(connectionInfo.deviceId)}_${safe(connectionInfo.clientId)}_${Date.now()}_${++this.fileSeq}.opus`;
        
        if (isShuttingDown || workerExited || !worker?.connected) {
            console.warn('子进程不可用，丢弃分片');
            connectionInfo.frames.length = 0;
            connectionInfo.frameCount = 0;
            return;
        }
        
        try {
            const framesToSave = connectionInfo.frames.splice(0);
            worker.send({ 
                type: 'opus_segment', 
                frames: framesToSave, 
                name 
            });
            console.log(`已保存OPUS文件: ${name}, 帧数: ${framesToSave.length}`);
        } catch (e) {
            console.error('发送到子进程失败:', e?.message || e);
        }
        
        connectionInfo.frameCount = 0;
    }

    start() {
        console.log('OPUS WebSocket服务器已启动');
    }

    stop() {
        console.log('正在停止OPUS WebSocket服务器...');
        isShuttingDown = true;
        
        // 保存所有连接的剩余数据
        for (const [socket, connectionInfo] of this.connections) {
            this.flushConnection(socket, true);
        }
        
        if (this.wss) {
            this.wss.close();
        }
        if (this.httpServer) {
            this.httpServer.close();
        }
        
        // 通知子进程退出
        if (!workerExited && worker?.connected) {
            try { worker.send({ type: 'exit' }); } catch { }
        }
        
        console.log('OPUS WebSocket服务器已停止');
    }
}

async function main() {
    const server = new OpusWebSocketServer({
        port: 4000
    });

    server.start();
    
    process.on('SIGINT', () => {
        console.log('\n正在停止服务器...');
        server.stop();
        
        // 等待子进程退出或兜底超时
        const timeout = setTimeout(() => process.exit(0), 5000);
        timeout.unref();
        const check = setInterval(() => {
            if (workerExited) {
                clearInterval(check);
                clearTimeout(timeout);
                process.exit(0);
            }
        }, 100);
        check.unref();
    });
}

if (import.meta.url === `file://${process.argv[1]}`) {
    main().catch(console.error);
}

export default OpusWebSocketServer;
